#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "DirectedRelationship.h"
#include "PackageableElement.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class ActivityEdge;
class Classifier;
class Connector;
class Message;
class NamedElement;
class Relationship;

/// <summary>
/// InformationFlow
/// InformationFlows describe circulation of information through a system in a
/// general manner. They do not specify the nature of the information, mechanisms by
/// which it is conveyed, sequences of exchange or any control conditions. During
/// more detailed modeling, representation and realization links may be added to
/// specify which model elements implement an InformationFlow and to show how
/// information is conveyed.  InformationFlows require some kind of “information
/// channel” for unidirectional transmission of information items from sources to
/// targets.  They specify the information channel’s realizations, if any, and
/// identify the information that flows along them.  Information moving along the
/// information channel may be represented by abstract InformationItems and by
/// concrete Classifiers.
/// </summary>
class UMLMODEL_EXPORT InformationFlow : public DirectedRelationship, public PackageableElement {

public: // Constructors and destructors
    explicit InformationFlow(const QString& umlType="uml::InformationFlow");

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Properties
    /// <summary>
    /// conveyeds getter
    /// Specifies the information items that may circulate on this information flow.
    /// </summary>
    vector<shared_ptr<Classifier>>& conveyeds();

    /// <summary>
    /// informationSources getter
    /// Defines from which source the conveyed InformationItems are initiated.
    /// </summary>
    vector<shared_ptr<NamedElement>>& informationSources();

    /// <summary>
    /// informationTargets getter
    /// Defines to which target the conveyed InformationItems are directed.
    /// </summary>
    vector<shared_ptr<NamedElement>>& informationTargets();

    /// <summary>
    /// realizations getter
    /// Determines which Relationship will realize the specified flow.
    /// </summary>
    vector<shared_ptr<Relationship>>& realizations();

    /// <summary>
    /// realizingActivityEdges getter
    /// Determines which ActivityEdges will realize the specified flow.
    /// </summary>
    vector<shared_ptr<ActivityEdge>>& realizingActivityEdges();

    /// <summary>
    /// realizingConnectors getter
    /// Determines which Connectors will realize the specified flow.
    /// </summary>
    vector<shared_ptr<Connector>>& realizingConnectors();

    /// <summary>
    /// realizingMessages getter
    /// Determines which Messages will realize the specified flow.
    /// </summary>
    vector<shared_ptr<Message>>& realizingMessages();

private: // Fields
    /// <summary>
    /// conveyeds
    /// Specifies the information items that may circulate on this information flow.
    /// </summary>
    vector<shared_ptr<Classifier>> conveyeds_;

    /// <summary>
    /// informationSources
    /// Defines from which source the conveyed InformationItems are initiated.
    /// </summary>
    vector<shared_ptr<NamedElement>> informationSources_;

    /// <summary>
    /// informationTargets
    /// Defines to which target the conveyed InformationItems are directed.
    /// </summary>
    vector<shared_ptr<NamedElement>> informationTargets_;

    /// <summary>
    /// realizations
    /// Determines which Relationship will realize the specified flow.
    /// </summary>
    vector<shared_ptr<Relationship>> realizations_;

    /// <summary>
    /// realizingActivityEdges
    /// Determines which ActivityEdges will realize the specified flow.
    /// </summary>
    vector<shared_ptr<ActivityEdge>> realizingActivityEdges_;

    /// <summary>
    /// realizingConnectors
    /// Determines which Connectors will realize the specified flow.
    /// </summary>
    vector<shared_ptr<Connector>> realizingConnectors_;

    /// <summary>
    /// realizingMessages
    /// Determines which Messages will realize the specified flow.
    /// </summary>
    vector<shared_ptr<Message>> realizingMessages_;

};

} // namespace uml
